export default class Text {
  constructor(txt) {
    const _this = this
    let parent = null

    _this.paragraphs = []
    _this.lines = []
    _this.lineHeight = 20
    _this.fontSize = 16
    _this.font = ''
    _this.dirty = true
    
    Object.defineProperties(this, {
      'tag': {
        value: 'text',
        configurable: false,
        writable: false,
        enumerable: false
      },
      data: {
        set(val){
          if(txt != val){
            txt = val
            _this.dirty = true
          }
        },
        get(){
          try{
            return txt.toString()
          }catch(err){
            return ''
          }
        }
      },
      parent: {
        set(val){
          if(val !== parent){
            parent = val
            _this.dirty = true
          }
        },
        get(){
          return parent
        }
      }
    })
  }
  compute(ctx) {
    const arr = typeof(this.data) === 'string' ? this.data.split(/\n/) : []
    const props = this.parent.props,
      reg = /[,，。\.\?？！!'"”“‘’、s\s》>`·]/,
      lhReg = /(?:\s+|^)([0-9.]+)(px)*(?:\/([0-9.]+)(px)*)?(?:\s+|$)/i,
      match = lhReg.exec(props.font),
      lines = []
    //获取行高
    if(match){
      this.fontSize = parseFloat(match[1]) || this.fontSize
      this.lineHeight = (match[4] ? parseFloat(match[3]) : this.fontSize * match[3]) || (this.fontSize + 4)
      this.font = props.font.replace(lhReg, this.fontSize + 'px/' + this.lineHeight+'px ')
      if(/px\s*$/.test(this.font)){
        this.font += ' arial,sans-serif'
      }
    }

    ctx.save()
    ctx.font = this.font
    for (let i = 0, len = arr.length, info=null, lineIndex = 0; i < len; i++) {
      let p = arr[i]
      info = ctx.measureText(p)
      if (info.width > props.width) {
        let n = Math.floor(props.width / this.fontSize), len = p.length
        for (let j = n; j < len; j++) {
          info = ctx.measureText(p.slice(0, j))
          if (info.width > props.width) {
            let sIndex = reg.test(p.charAt(j-1)) ? j : j-1
            lines[lineIndex++] = p.slice(0, sIndex)
            p = p.slice(sIndex)
            len = p.length
            j = len > n ? n : len
          }
        }
      }
      lines[lineIndex++] = p
    }
    this.lines = lines
    this.paragraphs = arr
    ctx.restore()
    this.dirty = false
  }
  render(ctx) {
    if(!ctx || !this.parent) return
    if(this.dirty) this.compute(ctx)
    const props = this.parent.props
    ctx.save()
    //字体
    ctx.font = this.font
    //垂直对齐固定值
    ctx.setTextBaseline('top')
    //阴影
    if (props.textShadow.length === 4) {
      ctx.shadowColor = props.textShadow[0]
      ctx.shadowOffsetX = props.textShadow[1]
      ctx.shadowOffsetY = props.textShadow[2]
      ctx.shadowBlur = props.textShadow[3]
    }
    //水平对齐
    ctx.setTextAlign(props.align)
    ctx.setFillStyle(props.color)
    //文字对齐方式对文字x坐标的影响
    let x = 0
    if (props.align === 'left') x = -props.width / 2
    if (props.align === 'right') x = props.width / 2
    this.lines.forEach((txt, k) => {
      ctx.fillText(txt, x, k * this.lineHeight - props.height / 2 + (this.lineHeight - this.fontSize) / 2)
    })
    //文字边框和渲染边框部分
    if (props.textBorder[0] > 0 && props.textBorder[1]) {
      ctx.setLineWidth(props.textBorder[0])
      ctx.setStrokeStyle(props.textBorder[1])
      this.lines.forEach((t, k) => {
        ctx.strokeText(t, x, k * this.lineHeight - props.height / 2 + (this.lineHeight - this.fontSize) / 2)
      })
    }
    ctx.restore()
  }
}